<script setup lang="ts">
import type { DynamicsColumnFieldProps } from '#/components/data-table/types';

import { nextTick, onUnmounted, ref } from 'vue';

import { VIcon } from '@croco/framework/icons';

import Sortable from 'sortablejs';

const visible = defineModel({ default: false });
const columns = defineModel<DynamicsColumnFieldProps[]>('columns', { default: [] });

const dragContainer = ref<HTMLElement>();
const sortableInstance = ref<null | Sortable>(null);
const checkAll = ref(false);
const indeterminate = ref(false);
const fixedLeftIndex = ref(0);
const fixedRightIndex = ref(0);

// 初始化拖拽排序
const initSortable = () => {
    if (!dragContainer.value) return;

    // 销毁旧实例（如果存在）
    if (sortableInstance.value) {
        sortableInstance.value.destroy();
    }

    sortableInstance.value = Sortable.create(dragContainer.value, {
        animation: 150,
        handle: '.is-drag',
        ghostClass: 'sortable-ghost',
        chosenClass: 'sortable-chosen',
        dragClass: 'sortable-drag',
        onMove: (evt) => {
            // 获取元素的数据属性
            const relatedIndex = Number.parseInt(evt.related.dataset.index || '0');
            // 不允许放置在左侧固定列或右侧固定列
            return !(relatedIndex <= fixedLeftIndex.value || relatedIndex >= fixedRightIndex.value);
        },
        onEnd: (evt) => {
            const { oldIndex, newIndex } = evt;
            if (oldIndex === undefined || newIndex === undefined || oldIndex === newIndex) return;

            // 再次验证位置是否允许(防止通过其他方式绕过onMove检查）)
            if (newIndex <= fixedLeftIndex.value || newIndex >= fixedRightIndex.value) {
                // 还原到原始位置
                if (dragContainer.value && evt.item) {
                    const originalItem = dragContainer.value.children[oldIndex + 1];
                    if (originalItem) {
                        dragContainer.value.insertBefore(evt.item, originalItem);
                    } else {
                        dragContainer.value.append(evt.item);
                    }
                }
                return;
            }

            // 创建新数组避免直接修改原数组
            const newColumns = [...columns.value];

            // 调整索引以匹配数据数组（排除标题行）
            // 移动元素
            const [movedItem] = newColumns.splice(oldIndex, 1);
            newColumns.splice(newIndex, 0, movedItem!!);

            // 更新序号
            newColumns.forEach((item, index) => (item.no = index));

            // 先按attrs.fixed('left'/'right')排序再按no排序
            toSort(newColumns);

            // 替换原数组触发响应式更新
            columns.value = newColumns;
        },
    });
};

const initCheckedStatus = () => {
    checkAll.value = columns.value.every((o) => o.visible);
    indeterminate.value = columns.value.some((o) => o.visible) && columns.value.some((o) => !o.visible);
};

const handleCheckAllChange = (value: boolean | number | string) => {
    columns.value.forEach((o) => (o.visible = value as boolean));
    initCheckedStatus();
};

// 固定
const handleFixedColumn = (column: DynamicsColumnFieldProps, value: string) => {
    column.attrs.fixed = column.attrs.fixed === value ? undefined : value;
    toSort(columns.value);
};

// 排序
function toSort(columns: DynamicsColumnFieldProps[]) {
    columns.sort((a, b) => {
        // 定义 fixed 的优先级: 'left' > undefined > 'right'
        const getFixedPriority = (fixed: any) => {
            if (fixed === 'left') return 0;
            if (fixed === 'right') return 2;
            return 1;
        };

        const priorityA = getFixedPriority(a.attrs.fixed);
        const priorityB = getFixedPriority(b.attrs.fixed);

        // 如果 fixed 优先级不同，按优先级排序
        if (priorityA !== priorityB) {
            return priorityA - priorityB;
        }

        // 如果 fixed 优先级相同，按 no 排序
        return a.no - b.no;
    });
    fixedLeftIndex.value = columns.filter((o) => o.attrs.fixed === 'left').length - 1;
    fixedRightIndex.value = columns.length - columns.filter((o) => o.attrs.fixed === 'right').length;
}

onBeforeMount(() => toSort(columns.value));

const onOpened = () => {
    nextTick(() => {
        initSortable();
        initCheckedStatus();
    });
};

onUnmounted(() => {
    if (sortableInstance.value) {
        sortableInstance.value.destroy();
        sortableInstance.value = null;
    }
});
</script>

<template>
    <el-drawer v-model="visible" class="dynamic-column" header-class="dynamic-column__header" title="列选项" @opened="onOpened" v-bind="$attrs">
        <template #default>
            <el-checkbox v-model="checkAll" :indeterminate="indeterminate" label="全部" @change="handleCheckAllChange" style="margin-left: 35px" />
            <div ref="dragContainer" class="column-list">
                <div v-for="(column, index) in columns" :key="column.prop" :data-index="index" class="dynamic-column__field">
                    <VIcon :class="`${!column.attrs.fixed && column.visible ? 'is-drag' : 'is-disabled'}`" icon="carbon:draggable" style="margin-right: 8px; transform: rotate(90deg)" />
                    <el-checkbox v-model="column.visible" :label="column.label" />
                    <div style="position: absolute; right: 5px">
                        <el-button :disabled="!column.visible" link :type="column.attrs.fixed === 'left' ? 'primary' : ''" @click="handleFixedColumn(column, 'left')">
                            <template #icon>
                                <VIcon icon="carbon:pin" />
                            </template>
                        </el-button>
                        <el-button :disabled="!column.visible" link :type="column.attrs.fixed === 'right' ? 'primary' : ''" @click="handleFixedColumn(column, 'right')">
                            <template #icon>
                                <VIcon icon="carbon:pin" style="transform: rotate(-90deg)" />
                            </template>
                        </el-button>
                    </div>
                </div>
            </div>
        </template>
    </el-drawer>
</template>

<style scoped>
.column-list {
    position: relative;
}

.dynamic-column__field {
    display: flex;
    align-items: center;
    padding: 8px 12px;
    margin-bottom: 4px;
    border-radius: 4px;
    transition: background-color 0.2s;
}

.dynamic-column__field:hover {
    background-color: hsl(var(--accent));
}

.is-drag {
    cursor: move;
}
.is-disabled {
    cursor: not-allowed;
    color: var(--el-color-info);
}

.el-button {
    width: var(--el-component-size);
    height: var(--el-component-size);
}
</style>

<style scoped>
.sortable-ghost {
    opacity: 0.5;
    background-color: hsl(var(--accent));
}

.sortable-chosen {
    background-color: hsl(var(--accent));
}

.sortable-drag {
    background-color: hsl(var(--accent));
}
</style>
